﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace Lon.Util
{
    public class NetDebugConsole
    {
        static Socket consoleServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        static NetDebugCmdManager cmdManager = new NetDebugCmdManager();

        public static NetDebugCmdManager CmdManager
        {
            get
            {
                return cmdManager;
            }
            
        }

        static LinkedList<String> messageBuf = new LinkedList<string>();


        static  List<INetDebugCmdFactory> cmdFactoryList = new List<INetDebugCmdFactory>();

        static LinkedList<NetDebugConsoleClient> clients = new LinkedList<NetDebugConsoleClient>();

        static int BufferCount=1000;

        static public int  Port=4445;
       
        public static void Init(int bufferCount)
        {
            BufferCount = bufferCount;
            cmdManager.AddDelegate("ClearLog", Clear);
            cmdManager.AddDelegate("ShowLog", ShowLogBuffer);
            cmdManager.AddDelegate("Say", Broadcast);
            cmdManager.AddDelegate("?", ShowCmdList);
            cmdManager.AddDelegate("help", ShowCmdList);
            cmdFactoryList.Add(cmdManager);
            Thread runThread = new Thread(new ThreadStart(RxProc));
            runThread.IsBackground = true;
            runThread.Start();

        }
        static void RxProc()
        {

            try
            {
                IPEndPoint ipe
                = new IPEndPoint(IPAddress.Any, Port);
                consoleServerSocket.Bind(ipe);
                consoleServerSocket.Listen(5);

                while (true)
                {
                    try
                    {
                        Socket clientSocket = consoleServerSocket.Accept();
                        NetDebugConsoleClient client = new NetDebugConsoleClient(clientSocket);
                        lock (clients)
                        {
                            clients.AddLast(client);
                            Broadcast(String.Format("[{0}]连接了调试控制台", client.Ip));
                            LinkedListNode<NetDebugConsoleClient> node = clients.First;
                            while (node != null)
                            {
                                LinkedListNode<NetDebugConsoleClient> next = node.Next;
                                if (node.Value.connected == false)
                                {
                                    clients.Remove(node);
                                }
                                node = next;
                            }
                        }

                    }
                    catch
                    {

                    }
                }
            }
            catch (System.Exception ex)
            {

            }



        }
    
        static public void WriteLine(String format,params object[] objs)
        {
            String message=null;
            try
            {
                message = String.Format(format, objs);
                message += "\r\n";
                if (messageBuf.Count > BufferCount)
                {
                    LinkedListNode<String> node = messageBuf.First;
                    messageBuf.RemoveFirst();
                    node.Value = message;
                    messageBuf.AddLast(node);

                }
                else
                {
                    messageBuf.AddLast(message);
                }
                
            }
            catch
            {
                return;
            }
           
        }

        static public void WriteLine(String message)
        {
          
            try
            {
                message += "\r\n";
                if (messageBuf.Count > BufferCount)
                {
                    LinkedListNode<String> node = messageBuf.First;
                    messageBuf.RemoveFirst();
                    node.Value = message;
                    messageBuf.AddLast(node);

                }
                else
                {
                    messageBuf.AddLast(message);
                }

            }
            catch
            {
                return;
            }

        }

        static public void AddCmdFactory(INetDebugCmdFactory factroy)
        {
            cmdFactoryList.Add(factroy);
        }

        static public void DoCmd(NetDebugCmd cmd)
        {
            DelegateNetDebugCmd temp;
            for (int i = 0; i < cmdFactoryList.Count; i++)
            {
                temp = cmdFactoryList[i].GetNetDebugCmdDelegate(cmd.CmdStr);
                if (temp != null)
                {
                    try
                    {
                        temp(cmd);
                    }
                    catch(Exception ex)
                    {
                        WriteLine(ex.Message + ex.StackTrace);
                    }
                }
            }
        }

        static private void ShowCmdList(NetDebugCmd cmd)
        {
            StringBuilder sb=new StringBuilder();
        
        
            for (int i = 0; i < cmdFactoryList.Count; i++)
            {
                String[] temp = cmdFactoryList[i].GetCmdList();
                for (int j = 0; j < temp.Length; j++)
                {
                    sb.AppendLine(temp[j]);
                }
            }
            cmd.RequertClient.Send(sb.ToString());
        }

        static private void ShowLogBuffer(NetDebugCmd cmd)
        {
            LinkedListNode<String> node = messageBuf.First;
            while (node != null)
            {
                LinkedListNode<String> next = node.Next;
                cmd.RequertClient.Send(node.Value);
                node = next;
            }
        }

        static private void Clear(NetDebugCmd cmd)
        {
             messageBuf.Clear();
             Broadcast(String.Format("日志缓存区被[{0}]清空",cmd.RequertClient.Ip));
        }

        static private void Broadcast(NetDebugCmd cmd)
        {
            if (cmd.Args.Length < 2) return;
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i < cmd.Args.Length; i++)
            {
                if (cmd.Args[i] != null)
                {
                    sb.Append(cmd.Args[i]);
                    sb.Append(" ");
                }
                
            }
            Broadcast(sb.ToString());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        static public void Broadcast(String message)
        {
            LinkedListNode<NetDebugConsoleClient> node = clients.First;
            while (node != null)
            {
                LinkedListNode<NetDebugConsoleClient> next = node.Next;
                if (node.Value.connected == false)
                {
                    continue;
                }
                node.Value.Send(message);
                node = next;
            }   
        }

        public static void SaveLogBuf()
        {
            StringBuilder sb=new StringBuilder();
              LinkedListNode<String> node = messageBuf.First;
            while (node != null)
            {
                LinkedListNode<String> next = node.Next;
                sb.Append(node.Value);
                node = next;
            }
            File.WriteAllText("C:\\log.txt", sb.ToString());
        }
    }
}
